/*
 * @Date         : 2024-05-12 15:25:45 星期0
 * @Author       : xut
 * @Description  :
 */
import grpc from "@grpc/grpc-js"
import helloStreamProto from "./helloworldstream.proto.js"

function streamingCall({
  client,
  requestId,
  name,
  num_greetings,
  expectedCode,
}) {
  console.log(`[${requestId}] Calling SayHelloStreamReply with name:"${name}"`)

  return new Promise((resolve, reject) => {
    const call = client.SayHelloStreamReply({ name, num_greetings })

    call.on("data", (value) => {
      console.log(`[${requestId}] Received response ${value.message}`)
    })

    // status 事件，不管成功和失败，都会执行。code 为对应状态码，detail 默认 grpc.status[status.code]，但会被 emit 中 detail 覆盖
    call.on("status", (status) => {
      console.log(
        `[${requestId}] Received status with code=${status.code} details=${status.details}`
      )
      resolve()
    })

    // end 事件，官网描述”事件表示服务器已完成发送，未发生任何错误。只会发出 'error' 或 'end' 中的一个。“
    // 但实际效果即使服务端在 emit error 之后没有再 emit end ，error 事件也会触发 end
    call.on("end", () => {
      console.log(`[${requestId}] Received end`)
    })

    // 'error' 事件表示发生错误并且流已关闭。
    call.on("error", (error) => {
      if (error.code === expectedCode) {
        console.log(`[${requestId}] Received expected error ${error.message}`) // message 即服务器 emit 中的 detail 值
      } else {
        console.log(`[${requestId}] Received unexpected error ${error.message}`)
      }
    })
  })
}

async function main() {
  const client = new helloStreamProto.MultiGreeter(
    "localhost:50051",
    grpc.credentials.createInsecure()
  )

  await streamingCall({
    client,
    requestId: 1,
    name: "",
    num_greetings: 1,
    expectedCode: grpc.status.INVALID_ARGUMENT,
  })
  console.log("==============================")
  await streamingCall({
    client,
    requestId: 2,
    name: "tom",
    num_greetings: "叁",
    expectedCode: grpc.status.INVALID_ARGUMENT,
  })
  console.log("==============================")
  await streamingCall({
    client,
    requestId: 3,
    name: "tom",
    num_greetings: 3,
    expectedCode: grpc.status.OK,
  })
}

main()
